﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using NHibernate;
using OpenGado.DATA;
using OpenGado.DATA.Entities;
using OpenGado.Business;

namespace OpenGado.Win
{
    public partial class frmOrders : Form
    {
        private PurchaseOrders currentOrder;
        private WorkMode currentMode;
        private int currentOrderId;

        private enum WorkMode
        {
            New, Edit
        }
        public frmOrders()
        {
            InitializeComponent();
            PopulateProjects();
            PopulateVendors();
            PopulateProducts();
            

            // hook up )
            this.dgvOrders.CellValueChanged += new System.Windows.Forms.DataGridViewCellEventHandler(this.dgvOrders_CellValueChanged);
            this.dgvOrders.RowsAdded += new System.Windows.Forms.DataGridViewRowsAddedEventHandler(this.dgvOrders_RowsAdded);
            this.dgvOrders.RowsRemoved += new System.Windows.Forms.DataGridViewRowsRemovedEventHandler(this.dgvOrders_RowsRemoved);
            
        }

        public frmOrders(int purchaseOrderId)
        {
            InitializeComponent();
            PopulateProjects();
            PopulateVendors();
            PopulateProducts();

            PopulateOrderData(purchaseOrderId);
            
            // hook up to an event
            this.dgvOrders.CellValueChanged += new System.Windows.Forms.DataGridViewCellEventHandler(this.dgvOrders_CellValueChanged);
            this.dgvOrders.RowsAdded += new System.Windows.Forms.DataGridViewRowsAddedEventHandler(this.dgvOrders_RowsAdded);
            this.dgvOrders.RowsRemoved += new System.Windows.Forms.DataGridViewRowsRemovedEventHandler(this.dgvOrders_RowsRemoved);
            tbOrder.TabPages[1].Enabled = true;

        }
        /// <summary>
        /// Populates the page with Order Data 
        /// </summary>
        private void PopulateOrderData(int purchaseOrderId)
        {
            dgvOrders.Rows.Clear();
            dgvReceiveOrders.Rows.Clear();

            // fetch the order object 

            PurchaseOrders order = PurchaseOrderDataControl.Instance.GetPurchaseOrderById(purchaseOrderId);
            
            currentOrder = order;
            // bind it to the page. 
            currentMode = WorkMode.Edit;
            
            SetOrderDetails(order);


        }

        private void SetOrderDetails(PurchaseOrders currentOrderHeader)
        {

            // should be only used in edit mode 

            if (currentMode == WorkMode.New) return;

            if (currentOrderHeader == null) return;


            if (currentOrderHeader.PoDate != null)
            {
                dtpOrderDate.Value = (DateTime)currentOrderHeader.PoDate;
            }
            cboVendor.SelectedItem = currentOrderHeader.Vendor;
            txtOrderNum.Text = currentOrderHeader.PurchaseOrderNum;
            txtOrderBy.Text = currentOrderHeader.PoInitiatedBy;
            cboOrderType.Text = currentOrderHeader.PoType;
            lblOrderStatus.Text = currentOrderHeader.PoStatus;
            lblOrderedOn.Visible = true;
            if (currentOrderHeader.PoDate != null)
                lblOrderedOn.Text = "Placed on: "+ currentOrderHeader.PoDate.Value.ToString();


            // cboProject.SelectedItem = currentOrderHeader.

            // putting the order items into the grid

            foreach (var i in currentOrderHeader.PurchaseOrderItems)
            {
                AddToGrid(i);
            }

        }


        private void PopulateProducts()
        {
            cboProduct.DataSource = GetProductList();
            cboProduct.DisplayMember = "ProductName";
        }
        /// <summary>
        /// Returns available list of projects
        /// </summary>
        /// <returns></returns>
        private IList<Project> GetProjectList()
        {
            IList<Project> projects = ProjectDataControl.Instance.GetAllProjects();

            return projects;
        }
        /// <summary>
        /// returns product list for selected project
        /// </summary>
        /// <param name="project"></param>
        /// <returns></returns>
        private IList<Product> GetProductList(Project project)
        {
            IList<Product> productList = new List<Product>();
            if (project != null)
            {
                productList = ProductDataControl.Instance.Query("Project", project.Name);
            }

            return productList;
        }

        private IList<Product> GetProductList()
        {
            IList<Product> productList = new List<Product>();
            productList = ProductDataControl.Instance.GetAll();

            return productList;
        }
        /// <summary>
        /// adds projects to the list
        /// </summary>
        private void PopulateProjects()
        {
            cboProject.DataSource = GetProjectList();
            cboProject.DisplayMember = "Name";

        }

        /// <summary>
        /// Binds to cbo vendors
        /// </summary>
        private void PopulateVendors()
        {
            cboVendor.DataSource = GetVendorList();
            cboVendor.DisplayMember = "VendorName";
        }

        /// <summary>
        /// returns a list of vendors
        /// </summary>
        /// <returns></returns>
        private IList<Vendor> GetVendorList()
        {
            IList<Vendor> vendorsList = VendorDataControl.Instance.GetAllVendors();

            return vendorsList;
        }



        private void btnAdd_Click(object sender, EventArgs e)
        {
          

            AddItemToGrid();
        }


        /// <summary>
        /// Creates the purchase order item and adds it to the grid.
        /// </summary>
        private void AddItemToGrid()
        {
            
            Decimal itemQuantity = 0;
            PurchaseOrderItems itemToAdd = new PurchaseOrderItems();
            itemToAdd.Product = (Product) cboProduct.SelectedItem;
            Decimal.TryParse(txtQuantity.Text, out itemQuantity);
            itemToAdd.Quantity = itemQuantity;
            AddToGrid(itemToAdd);


        }

        private int productExists(int idToCheck)
        {
            int exists = -1;

            if (dgvOrders.Rows.Count == 1)
            {
                return exists;
            }
            foreach (DataGridViewRow rw in dgvOrders.Rows)
            {
                if (rw.Cells[0].Value == null)
                {
                    break;
                }
                else if (idToCheck == (int)rw.Cells[0].Value)
                {
                    exists = rw.Index;
                    break;
                }


            }

            return exists;
        }


       

        private void AddToGrid(PurchaseOrderItems currentItem)
        {
            if (currentItem == null) return;

            decimal orderQuantity = 0;
            decimal subTotal = 0;
            Product product = currentItem.Product;
            Vendor vendor = null;

            DataGridViewRow rw = new DataGridViewRow();

            int r = dgvOrders.Rows.Add(rw);

            dgvOrders.Rows[r].Cells[0].Tag = currentItem;
            //dgvOrders.Rows[r].Cells[0].Value = product.Productid;
            dgvOrders.Rows[r].Cells[1].Tag = product;
            dgvOrders.Rows[r].Cells[1].Value = product.ProductName;
            dgvOrders.Rows[r].Cells[2].Value = product.ProductDescription;
            dgvOrders.Rows[r].Cells[3].Value = product.ManufacturerCode;
            dgvOrders.Rows[r].Cells[4].Value = currentItem.Quantity;
            dgvOrders.Rows[r].Cells[5].Value = product.CurrentPrice;
            if (product.CurrentPrice != null)
            {
                subTotal = (orderQuantity * (Decimal) product.CurrentPrice);
            }
            dgvOrders.Rows[r].Cells[6].Value = subTotal;

            // do the same for the second grid
           AddToReceiveGrid(currentItem);


            CalculateSubTotals();
            DisplayTotal();

        }


        private void AddToReceiveGrid(PurchaseOrderItems currentItem)
        {
            if (currentItem == null) return;
           // dont add already received items, we can receive same thing twice.
            if (currentItem.ReceivedStatus =="Received")return;

                Product product = currentItem.Product;
                decimal orderQuantity = 0;
                DataGridViewRow receivedRow = new DataGridViewRow();
                      
                int s = dgvReceiveOrders.Rows.Add(receivedRow);


                dgvReceiveOrders.Rows[s].Cells[0].Tag = currentItem;

                dgvReceiveOrders.Rows[s].Cells[1].Tag = product;
                dgvReceiveOrders.Rows[s].Cells[1].Value = product.ProductName;
                dgvReceiveOrders.Rows[s].Cells[2].Value = product.ProductDescription;
                dgvReceiveOrders.Rows[s].Cells[3].Value = product.ManufacturerCode;
                dgvReceiveOrders.Rows[s].Cells[4].Value = currentItem.QuantityReceived;
                dgvReceiveOrders.Rows[s].Cells[5].Value = product.CurrentPrice;
                dgvReceiveOrders.Rows[s].Cells[6].Value = (orderQuantity * product.CurrentPrice);
           
            CalculateSubTotalsReceived();
            
        }

        private List<int> GetSelectedProducts()
        {
            List<int> selectedProducts = new List<int>();

            foreach (DataGridViewRow rw in dgvOrders.SelectedRows)
            {
                selectedProducts.Add((int)rw.Cells[0].Value);
            }

            return selectedProducts;
        }



        /// <summary>
        /// Calculates sub totals
        /// </summary>
        private void CalculateSubTotals()
        {
            if (dgvOrders.Rows.Count == 1) return;

            Decimal itemQuantity=0;
            Decimal price =0;
            Decimal subTotal =0;

            foreach (DataGridViewRow rw in dgvOrders.Rows)
            {
                if (rw.Cells[4].Value != null)
                {
                    Decimal.TryParse(rw.Cells[4].Value.ToString(), out itemQuantity);
                   
                }
                if (rw.Cells[5].Value !=null)
                {
                    Decimal.TryParse(rw.Cells[5].Value.ToString(), out price);
                }
               
                subTotal = itemQuantity * price;
                
                rw.Cells[6].Value = subTotal;


            }

            DisplayTotal();
        }


        /// <summary>
        /// Calculates sub totals
        /// </summary>
        private void CalculateSubTotalsReceived()
        {
            if (dgvReceiveOrders.Rows.Count == 1) return;

            Decimal itemQuantity = 0;
            Decimal price = 0;
            Decimal subTotal = 0;

            foreach (DataGridViewRow rw in dgvReceiveOrders.Rows)
            {
                if (rw.Cells[4].Value != null)
                {
                    Decimal.TryParse(rw.Cells[4].Value.ToString(), out itemQuantity);

                }
                if (rw.Cells[5].Value != null)
                {
                    Decimal.TryParse(rw.Cells[5].Value.ToString(), out price);
                }

                subTotal = itemQuantity * price;

                rw.Cells[6].Value = subTotal;


            }

            DisplayTotal();
        }
        private void DisplayTotal()
        {
            txtTotal.Text = GetTotal().ToString();
            txtReceivedTotal.Text = GetReceivedTotal().ToString();
        }


        private Decimal GetTotal()
        {
            Decimal itemValue = 0;

            Decimal runningValue = 0;


            foreach (DataGridViewRow rw in dgvOrders.Rows)
            {
                if (rw.Cells[6].Value != null)
                {
                    Decimal.TryParse(rw.Cells[6].Value.ToString(), out itemValue);
                    runningValue += itemValue;
                }

            }

            return runningValue;
        }

        private Decimal GetReceivedTotal()
        {
            Decimal itemValue = 0;     
            Decimal runningValue = 0;
            // 6 index of subtotal column 

            foreach (DataGridViewRow rw in dgvReceiveOrders.Rows)
            {
                if (rw.Cells[6].Value != null)
                {
                    Decimal.TryParse(rw.Cells[6].Value.ToString(), out itemValue);
                    runningValue += itemValue;
                }

            }

            return runningValue;
        }
        /// <summary>
        /// Places the order
        /// </summary>
        private void PlaceOrder()
        {
            if (currentMode == WorkMode.New)
            {
                Decimal purchasePrice = 0;
                // Update product vendor and price 
                foreach (DataGridViewRow rw in dgvOrders.Rows)
                {
                    if (rw.Cells[0].Tag == null) break;

                    var item = (PurchaseOrderItems) rw.Cells[0].Tag;
                    var p = (Product) rw.Cells[1].Tag;

                    Decimal price = 0 ;
                    Decimal.TryParse(rw.Cells[5].Value.ToString(), out price);
                   
                    // save this info    
                    if (p.CurrentPrice != price)
                    {
                        p.CurrentPrice = price;
                        ProductDataControl.Instance.Save(p);
                    }
                   

                }

               // Save order to the database 
                currentOrder = new PurchaseOrders
                                   {
                                       PoDate = dtpOrderDate.Value,
                                       PurchaseOrderNum = txtOrderNum.Text,
                                       PoInitiatedBy = txtOrderBy.Text,
                                       Vendor = (Vendor) cboVendor.SelectedItem,
                                       PoRemarks = txtRemarks.Text,
                                       PoType = cboOrderType.Text,
                                       PoStatus = "Open",
                                       PoTimestamp = DateTime.Now,
                                       Paymentmethod = cboPaymentMethod.Text
                                   };

               

                PurchaseOrderDataControl.Instance.Save(currentOrder);
 
                foreach (DataGridViewRow rx in dgvOrders.Rows)
                {
                    if (rx.Cells[0].Tag == null) break;

                    var item = (PurchaseOrderItems) rx.Cells[0].Tag;
                    item.PurchaseOrders = currentOrder;
                    item.Product = (Product) rx.Cells[1].Tag;
                    item.Quantity = (Decimal) rx.Cells[4].Value;
                    Decimal.TryParse(rx.Cells[5].Value.ToString(), out purchasePrice);
                    item.PurchasePrice = purchasePrice;
                    item.PurchaseOrders = currentOrder;
                   
                        
                    PurchaseOrderDataControl.Instance.Save(item);
                    // put it back in the Tag. 

                    rx.Cells[0].Tag = item;
                }
                
                // set mode to edit so that same item doesnt get created twice 

                currentMode = WorkMode.Edit;

            }

            if (currentMode == WorkMode.Edit)
            {
                List<PurchaseOrderItems> itemsToPurchase = new List<PurchaseOrderItems>();

                PurchaseOrderItems p;
                Decimal itemPrice;
                Decimal itemQuantity; 

                foreach (DataGridViewRow rx in dgvOrders.Rows)
                {
                    p = (PurchaseOrderItems) rx.Cells[0].Tag;
                    Decimal.TryParse(rx.Cells[4].Value.ToString(), out itemQuantity);
                    p.Quantity = itemQuantity;
                    Decimal.TryParse(rx.Cells[5].Value.ToString(), out itemPrice);
                    p.PurchasePrice = itemPrice;
                    p.PurchaseOrders = currentOrder;
                    itemsToPurchase.Add(p);

                    PurchaseOrderDataControl.Instance.Save(p);
                }

                currentOrder.PoDate = dtpOrderDate.Value;
                currentOrder.PurchaseOrderNum = txtOrderNum.Text;
                currentOrder.PoInitiatedBy = txtOrderBy.Text;
                currentOrder.Vendor = (Vendor) cboVendor.SelectedItem;
                currentOrder.PoRemarks = txtRemarks.Text;
                currentOrder.PoType = cboOrderType.Text;
                currentOrder.PoStatus = "Open";
                currentOrder.PoTimestamp = DateTime.Now;
                currentOrder.Paymentmethod = cboPaymentMethod.Text;
                currentOrder.PurchaseOrderItems = itemsToPurchase;
                PurchaseOrderDataControl.Instance.Save(currentOrder);


            }
           // notify user 

        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void cboProduct_SelectedValueChanged(object sender, EventArgs e)
        {
            Product p = (Product)cboProduct.SelectedItem;
            txtQuantity.Text = p.ProductReorderLevel.ToString();
        }

        private void dgvOrders_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
        {
             DisplayTotal();
        }

        private void dgvOrders_RowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
        {
             DisplayTotal();
        }

        private void btnOrder_Click(object sender, EventArgs e)
        {
            ep.Clear();

            if (String.IsNullOrEmpty(txtOrderNum.Text))
            {
                ep.SetError(txtOrderNum, "Order Number is required");
            }
            PlaceOrder();
        }

        private void frmOrders_Load(object sender, EventArgs e)
        {

        }

        private void dgvOrders_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            CalculateSubTotals();
        }

        private void btnReceive_Click(object sender, EventArgs e)
        {
           ReceiveItems();
           PopulateOrderData(currentOrder.PurchaseOrderId);
        }

        /// <summary>
        /// Gets a list of selected order items to receive. 
        /// </summary>
        /// <returns></returns>
        private List<PurchaseOrderItems> GetItemsToReceive()
        {

            var  receivedItemsList = new List<PurchaseOrderItems>();

            foreach (DataGridViewRow rw in dgvReceiveOrders.Rows)
            {
               
                if ((bool)rw.Cells[0].Value)
                {
                    PurchaseOrderItems p = (PurchaseOrderItems) rw.Cells[0].Tag;
                    Decimal receivedQuantity;

                    Decimal.TryParse(rw.Cells[4].Value.ToString(), out receivedQuantity);
                    p.QuantityReceived = receivedQuantity;
                    receivedItemsList.Add(p);
                }
            }

            return receivedItemsList; 
        }
        /// <summary>
        /// Receives items 
        /// </summary>
        private void ReceiveItems()
        {
            PurchaseOrderBusiness pb = new PurchaseOrderBusiness();
             pb.ReceiveOrder(currentOrder, GetItemsToReceive());   
        }

        private void chkAll_CheckStateChanged(object sender, EventArgs e)
        {
            if (chkAll.Checked)
            {
                foreach (DataGridViewRow rw in dgvReceiveOrders.Rows)
                {
                    rw.Cells[0].Value = true;
                }
            }
            else
            {
                foreach (DataGridViewRow rw in dgvReceiveOrders.Rows)
                {
                    rw.Cells[0].Value = false;
                }
            }
        }

        private void dgvOrders_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            if (e != null)
            {
                var poi = (PurchaseOrderItems) e.Row.Cells[0].Tag;

                PurchaseOrderDataControl.Instance.Delete(poi);
            }
        }

        private void dgvReceiveOrders_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            CalculateSubTotalsReceived();
            
        }

        private void cboProject_SelectedValueChanged(object sender, EventArgs e)
        {
            OrdersBusiness ob = new OrdersBusiness();
            var project = new Project();
            project = (Project) cboProject.SelectedItem;
            txtOrderNum.Text =  ob.GenOrderNumber(project.Code);
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            DialogResult res = MessageBox.Show("Are you sure you want to delete this order", "Inventory",
                                               MessageBoxButtons.YesNo);
            if (res == DialogResult.No) return;

            DeleteOrder();
            
            this.Close();
        }
        /// <summary>
        /// Deletes the current order
        /// </summary>
        private void DeleteOrder()
        {

                if (currentOrder != null)
                {
                    foreach (var p in currentOrder.PurchaseOrderItems)
                    {
                        PurchaseOrderDataControl.Instance.Delete(p);
                    }
                    
                    PurchaseOrderDataControl.Instance.Delete(currentOrder);
                }
        }
    }
}